package edu.ccut.saturn.component.impl;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import edu.ccut.saturn.component.IValidate;
import edu.ccut.saturn.component.IValidateInfo;
import edu.ccut.saturn.component.loader.ValidateLoader;
import edu.ccut.saturn.component.xml.ISaturnElement;
import edu.ccut.saturn.component.xml.SaturnElement;

/**
 * Record a validate information
 * 
 * @author LeslieGu
 * 
 */
public class SaturnValidateInfo implements IValidateInfo {

	private String fullKey;

	private String key;

	private String name;

	private String description;

	private Map<String, String> errorInfos;

	private Class<? extends IValidate> classType;

	private List<String> args;

	private String jsMethodName;

	private String custemJSMethodInfo;

	private String classTypeStr;

	private List<String> eventInfos;

	private String validateType;

	public List<String> getArgs() {
		return args;
	}

	public void setArgs(List<String> args) {
		this.args = args;
	}

	public SaturnValidateInfo(String key, String name, String description,
			Map<String, String> errorInfos, List<String> args, String type,
			List<String> eventInfos, String validateType) {

		this.key = key;
		this.name = name;
		this.description = description;
		this.classType = null;
		this.args = args;
		this.errorInfos = errorInfos;
		this.classTypeStr = type;
		this.eventInfos = eventInfos;
		this.validateType = validateType;
	}
	
	public SaturnValidateInfo(String key, String name, String description,
			Map<String, String> errorInfos,
			Class<? extends IValidate> classType, List<String> args,
			String type, List<String> eventInfos, String validateType) {

		this.key = key;
		this.name = name;
		this.description = description;
		this.classType = classType;
		this.args = args;
		this.errorInfos = errorInfos;
		this.classTypeStr = type;
		this.eventInfos = eventInfos;
		this.validateType = validateType;
	}

	// public SaturnValidateInfo(String key, String name, String description,
	// Class<? extends IValidate> classType, String type) {
	//
	// this.key = key;
	// this.name = name;
	// this.description = description;
	// this.classType = classType;
	// this.args = null;
	// this.errorInfo = null;
	// this.classTypeStr = type;
	// }

	public SaturnValidateInfo(IValidateInfo saturnValidateInfo) {
		this(saturnValidateInfo.getKey(), saturnValidateInfo.getName(),
				saturnValidateInfo.getDescription(), saturnValidateInfo
						.getErrorInfos(), saturnValidateInfo.getClassType(),
				null, saturnValidateInfo.getClassTypeStr(), saturnValidateInfo
						.getEventInfos(), saturnValidateInfo.getValidateType());
		this.fullKey = saturnValidateInfo.getValidateInfoFullkey();
		this.args = new LinkedList<String>();

		if (saturnValidateInfo.getArgs() != null) {
			this.args.addAll(saturnValidateInfo.getArgs());
		}

		this.errorInfos = new HashMap<String, String>();

		if (saturnValidateInfo.getErrorInfos() != null) {
			this.errorInfos.putAll(saturnValidateInfo.getErrorInfos());
		}

		this.eventInfos = new LinkedList<String>();

		if (saturnValidateInfo.getEventInfos() != null) {
			this.eventInfos.addAll(saturnValidateInfo.getEventInfos());
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.ccut.saturn.component.impl.IValidateInfo#getKey()
	 */
	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		this.key = key;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.ccut.saturn.component.impl.IValidateInfo#getName()
	 */
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.ccut.saturn.component.impl.IValidateInfo#getDescription()
	 */
	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.ccut.saturn.component.impl.IValidateInfo#getClassType()
	 */
	public Class<? extends IValidate> getClassType() {
		return classType;
	}

	public void setClassType(Class<? extends IValidate> classType) {
		this.classType = classType;
	}

	public String getJSMethodName() {
		return jsMethodName;
	}

	public void setJSMethodName(String jsMethodName) {
		this.jsMethodName = jsMethodName;
	}

	public String getCustemJSMethodInfo() {
		return custemJSMethodInfo;
	}

	public void setCustemJSMethodInfo(String custemJSMethodInfo) {
		this.custemJSMethodInfo = custemJSMethodInfo;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.ccut.saturn.component.impl.IValidateInfo#createValidate()
	 */
	public IValidate createValidate() {
		try {
			IValidate validate = null;

			if (this.classType != null) {
				validate = this.classType.newInstance();
			}

			if (validate != null) {
				// validate.setValidateKey(this.key);
				validate.setErrorInfos(this.errorInfos);
			}
			return validate;

		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((classType == null) ? 0 : classType.hashCode());

		result = prime * result + ((key == null) ? 0 : key.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {

		if (this == obj) {
			return true;
		}

		if (obj == null) {
			return false;
		}

		if (getClass() != obj.getClass()) {
			return false;
		}
		final SaturnValidateInfo other = (SaturnValidateInfo) obj;

		if (classType == null) {

			if (other.classType != null)
				return false;

		} else if (!classType.equals(other.classType))
			return false;

		if (key == null) {

			if (other.key != null) {
				return false;
			}

		} else if (!key.equals(other.key)) {
			return false;
		}
		return true;
	}

	public String toString() {
		return "[" + this.key + ", " + this.args + "]";
	}

	public void setErrorInfo(Map<String, String> errorInfos) {
		this.errorInfos = errorInfos;
	}

	public Map<String, String> getErrorInfos() {
		return this.errorInfos;
	}

	public String getClassTypeStr() {
		return this.classTypeStr;
	}

	public List<String> getEventInfos() {
		return this.eventInfos;
	}

	public void setEventInfos(List<String> eventInfos) {
		this.eventInfos = eventInfos;
	}

	public String getValidateType() {
		return this.validateType;
	}

	public void setValidateType(String validateType) {
		this.validateType = validateType;
	}

	public ISaturnElement toSaturnElement() {
		ISaturnElement validateInfoElement = new SaturnElement(
				ValidateLoader.KEY_NODETYPE_VALIDATE);

		ISaturnElement keyElement = new SaturnElement(
				ValidateLoader.KEY_VALIDATE_KEY, this.key);

		ISaturnElement nameElement = new SaturnElement(
				ValidateLoader.KEY_VALIDATE_NAME, this.name);

		ISaturnElement classElement = new SaturnElement(
				ValidateLoader.KEY_VALIDATE_CLASS, this.classTypeStr);

		ISaturnElement descriptionElement = new SaturnElement(
				ValidateLoader.KEY_VALIDATE_DESCRIPTION, this.description);

		ISaturnElement jsMethodElement = new SaturnElement(
				ValidateLoader.KEY_VALIDATE_JSMETHODNAME, this.jsMethodName);

		ISaturnElement customJSMethodElement = new SaturnElement(
				ValidateLoader.KEY_VALIDATE_CUSTOMJSMETHOD,
				this.custemJSMethodInfo);

		if (this.validateType != null && !"".equals(this.validateType)) {
			ISaturnElement validateTypeElement = new SaturnElement(
					ValidateLoader.KEY_VALIDATE_VALIDATETYPE, this.validateType);

			validateInfoElement.addSubElement(validateTypeElement);
		}
		ISaturnElement argsElement = new SaturnElement(
				ValidateLoader.KEY_VALIDATE_ARGS);

		if (this.args != null) {

			for (String argument : this.args) {
				ISaturnElement argElement = new SaturnElement(
						ValidateLoader.KEY_VALIDATE_ARGS_ARG, argument);

				argsElement.addSubElement(argElement);
			}
		}
		ISaturnElement errorInfosElement = new SaturnElement(
				ValidateLoader.KEY_VALIDATE_ERRORINFOS);

		if (this.errorInfos != null) {

			for (String errorKey : this.errorInfos.keySet()) {
				ISaturnElement errorInfoElement = new SaturnElement(
						ValidateLoader.KEY_ERRORINFOS_ERRORINFO,
						this.errorInfos.get(errorKey));
				errorInfoElement.addAttribute(ValidateLoader.KEY_ERRORINFO_KEY, errorKey);
				errorInfosElement.addSubElement(errorInfoElement);
			}
		}

		if (this.eventInfos != null) {
			ISaturnElement eventsInfoElement = new SaturnElement(
					ValidateLoader.KEY_VALIDATE_EVENTINFOS);

			for (String eventInfo : this.eventInfos) {
				ISaturnElement eventInfoElement = new SaturnElement(
						ValidateLoader.KEY_EVENTINFOS_EVENTINFO, eventInfo);

				eventsInfoElement.addSubElement(eventInfoElement);
			}
			validateInfoElement.addSubElement(eventsInfoElement);
		}
		validateInfoElement.addSubElement(keyElement);
		validateInfoElement.addSubElement(nameElement);
		validateInfoElement.addSubElement(classElement);
		validateInfoElement.addSubElement(descriptionElement);
		validateInfoElement.addSubElement(jsMethodElement);
		validateInfoElement.addSubElement(customJSMethodElement);
		validateInfoElement.addSubElement(argsElement);
		validateInfoElement.addSubElement(errorInfosElement);
		return validateInfoElement;
	}

	public String toXmlStr() {
		ISaturnElement saturnElement = toSaturnElement();
		return saturnElement.getXMLStr();
	}

	public void setClassTypeStr(String classTypeStr) {
		this.classTypeStr = classTypeStr;
	}

	public void setErrorInfos(Map<String, String> errorInfos) {
		this.errorInfos = errorInfos;
	}

	public String getValidateInfoFullkey() {
		return this.fullKey;
	}

	public void setValidateInfoFullkey(String fullkey) {
		this.fullKey = fullkey;
	}
}
